import { Inject, Service } from "typedi";
import { RedirectParams, SuccessCallback } from "client/loginVo";
import {
  LOGIN_DOMAIN,
  CALLBACK_URL,
  CLIENT_ID,
  TOKEN_PATH,
  AUTHORIZE_PATH,
} from "config/config";
import { getToken, getIp, ERR_ALL_PROMISE, RES_INFO } from "config/const";
import { createToken, setRedis } from "config/redis";

import {
  httpLoginInterface,
  HTTP_LOGIN_INTERFACE,
} from "infrastructure/http/login";
import {
  repoConfigInterface,
  REPO_CONFIG_INTERFACE,
} from "infrastructure/rpc/configRepo";

const { AuthorizationCode } = require("simple-oauth2");

export const LOGIN_INTERFACE = "loginInterface";

export interface loginInterface {
  getRedirectUrl(opts: any): RedirectParams;
  afterCallBack(opts: any): Promise<SuccessCallback>;
  getUserInfo(opts: any): Promise<SuccessCallback>;
  accStructure(opts: any): Promise<SuccessCallback>;
}

const client = new AuthorizationCode({
  client: {
    id: CLIENT_ID,
    secret: "",
  },
  auth: {
    tokenHost: LOGIN_DOMAIN,
    tokenPath: TOKEN_PATH,
    authorizePath: AUTHORIZE_PATH,
  },
});

@Service(LOGIN_INTERFACE)
export class Login implements loginInterface {
  @Inject(HTTP_LOGIN_INTERFACE) private readonly loginRepo: httpLoginInterface;
  @Inject(REPO_CONFIG_INTERFACE)
  private readonly configRepo: repoConfigInterface;

  // 获取重定向url
  getRedirectUrl(opts: any): RedirectParams {
    const { request, response } = opts;
    const { callback } = request.query || {};
    const getAuthorizationUri = (callback: string) => {
      const authorizationUri = client.authorizeURL({
        redirect_uri:
          CALLBACK_URL + "?callback=" + encodeURIComponent(callback),
        state: "random",
      });
      return authorizationUri;
    };
    const authorizationUri = getAuthorizationUri(callback) || "";
    return { url: authorizationUri };
  }

  // 成功回调
  afterCallBack(opts: any): Promise<SuccessCallback> {
    const { request, response } = opts;
    return new Promise((resolve, reject) => {
      const { code, callback } = request.query || {};
      this.loginRepo.getToken(code).then((res) => {
        if (res?.no !== 0) return resolve(res);
        this.getUserInfoByToken({
          token: res.data.access_token,
          request,
          response,
        }).then((token) => {
          if (res?.no !== 0) return resolve(res);
          resolve({ url: callback, token });
        });
      });
    });
  }

  // 获取用户信息
  getUserInfoByToken(opts: any): Promise<SuccessCallback> {
    const { token, request, response } = opts;
    return new Promise((resolve, reject) => {
      this.loginRepo.getUserInfo(token).then((res) => {
        if (res?.no !== 0) return resolve(res);
        const userInfo = res.data || {};
        const bffToken = createToken(userInfo);
        setRedis(bffToken, JSON.stringify(userInfo));
        // response.setHeader("Set-Cookie", `OAUTH2=${token};Path=/;`);
        resolve(bffToken);
      });
    });
  }

  // 实时获取用户信息
  getUserInfo(opts: any): Promise<SuccessCallback> {
    const { userInfo, request, response } = opts;
    return new Promise((resolve, reject) => {
      this.loginRepo.getUserInfoById(opts).then((res: any) => {
        if (res?.no !== 0) return resolve(res);
        const userInfo = res.data || {};
        userInfo.ip = getIp(request);
        setRedis(getToken(request), JSON.stringify(userInfo));
        resolve(res);
      });
    });
  }

  // 获取所有人员
  accStructure(opts: any): Promise<SuccessCallback> {
    return new Promise(async (resolve, reject) => {
      const resList = await Promise.all([this.configRepo.accStructure(opts)]);
      const errRes = ERR_ALL_PROMISE(resList);
      if (errRes) return resolve(errRes);
      const [allList] = resList;
      resolve(
        RES_INFO({
          data: allList.data,
        })
      );
    });
  }
}
